;<135-TENEX>SIGNAL.MAC;57 11-Aug-76 16:17:35 EDIT BY CALVIN ; Move NOINT at .SIGNL+4 to .SIGNL+1 since SGNWAT should be called NOINT ;<135-TENEX>SIGNAL.MAC;56 9-FEB-76 10:09:58 EDIT BY PLUMMER ; FIX NOINT STUFF AT SIGNL4 ;<135-TENEX>SIGNAL.MAC;55 4-FEB-76 10:13:09 EDIT BY PLUMMER ; FIX LOST FLAGS IN WTFOR0 ; CORRECT CHECK ON "DONT WAIT" BIT IN WTFOR0 ;<134-TENEX>SIGNAL.MAC;53 28-AUG-75 14:03:56 EDIT BY PLUMMER ; ADD "PEEK" OPTION TO WTFOR ;<134-TENEX>SIGNAL.MAC;51 28-AUG-75 11:59:00 EDIT BY PLUMMER ; ADD GTSIG FLAG WHICH REQUIRES ASSIGNMENT OF A SYSTEM SIGNAL ; FIX ACCESSIBILTY CHECKS IN SIGNL ;<134-TENEX>SIGNAL.MAC;48 2-APR-75 11:27:48 EDIT BY PLUMMER ; SIGNAL WAITS FOR PREVIOUS DATA TO BE READ ONLY IF NEW DATA SUPPLIED ;<134-TENEX>SIGNAL.MAC;47 13-MAR-75 15:56:28 EDIT BY PLUMMER ; FIX RLSIG ;<134-TENEX>SIGNAL.MAC;46 12-MAR-75 22:13:40 EDIT BY PLUMMER ; MAKE WTFOR RETURN SIGNL-ER'S JOB NUMBER IN RH(3) IF DATA RETURNED ; REPAIRS, REARRANGE, ETC ;<134-TENEX>SIGNAL.MAC;40 12-MAR-75 09:59:03 EDIT BY PLUMMER ; INCLUDE CHANGES BY TOMLINSON ;<134-TENEX>SIGNAL.MAC;39 11-MAR-75 18:09:43 EDIT BY PLUMMER SEARCH STENEX,PROLOG IFDEF SIGIPC,< ;ASSEMBLE ONLY IF CONFIGURATION REQUIRES TITLE SIGNAL SUBTTL WILLIAM W. PLUMMER, 25FEB75 SID= T2=2 T3=3 T4=4 INTERN .GTSIG,.RLSIG,.SIGNL,.WTFOR INTERN SIGINI,WTFORT,SIGKIL,RMJBRF EXTERN MENTR,MRETN,MRETNE,SKMRTN EXTERN CAPENB,FKJOB,JOBRT,LSTERR,MINUS1 EXTERN EDISMS,DISGE,FORKX,JOBNO DEFINE RETERR(CODE,EXTRA)< JRST [ EXTRA IFDIF ,<>, JRST MRETNE]> LS (SIGLCK,1) ;LOCK ON SIG TABLES LS (SIGNAL,NSSIGS+NUSIGS) ;SEMAPHORE CELLS: RUN IF AOSLE SKIPS LS (SIGJOB,NSSIGS+NUSIGS) ;FLAGS,,OWNING JOB OR -1 IF NOT IN USE LS (SIGQUE,NSSIGS+NUSIGS) ;SIGNL FORK QUEUE: IN,,OUT LS (SIGJB1,NSSIGS+NUSIGS) ;JOBS ALLOWED TO SIGNL THIS SID LS (SIGJB2,NSSIGS+NUSIGS) ;... LS (FKDATA,NFKS) ;SIGNL DATA WORD LS (FKLIST,NFKS) ;SID,,Q-POINTER. B0: DATA QUEUED ; B1: SID VALID ;TEMPORARY DEFINITIONS UNTIL PUT INTO ERRMES SGNLX1==602001 SGNLX2==602002 SGNLX3==602003 SGNLX4==602004 SGNLX5==602005 SGNLX6==602006 SGNLX7==602007 SGNLX8==602010 SGNLX9==602011 USE SWAPPC ;GET SIGNAL ID ;1/ FLAGS,,COUNT ;B0: MAKE ACCESSIBLE TO JOBS IN 2,3,... ;B4: REQUIRE SYSTEM SIGNAL ; ;B3: MAKE ACCESSIBLE TO ALL JOBS ;2,3/ 9-BIT BYTES: 777 OR JOB # IN EACH ; ; GTSIG ; ;R+1: ERROR, NUMBER IN 1 ;R+2: OK, SID IN 1 .GTSIG::JSYS MENTR ;ENTER MONITOR NOINT TLNN 1,(1B0) ;MAKE ACCESSIBLE TO OTHER JOBS? SETOB 2,3 ;NO. USE NULL JOB NUMBERS FOR CHECKS PUSH P,2 PUSH P,3 PUSH P,1 GTSIG1: MOVE T2,[POINT 9,-2(P)] MOVEI T3,4*2 ;NUMBER OF JOBS TO CHECK CALL LOCKSG ;LOCK THE SIGNAL TABLES NOSKED ;STOP ALL OTHER FORKS GTSI11: ILDB T1,T2 ;GET NEXT JOB NUMBER CAIN T1,777 ;NULL? JRST GTSI19 ;YES, SKIP CHECK CAIL T1,0 ;REASONABLE? CAIL T1,NJOBS RETERR(SGNLX1,) ;"BAD JOB SPEC" SKIPGE JOBRT(T1) ;LOGGED IN? RETERR(SGNLX1,) GTSI19: SOJG T3,GTSI11 ;LOOP OVER ALL BYTES GTSIG2: MOVEI T2,WHEEL!OPER MOVSI T3,(1B4) ;REQUIRE SYSTEM SIGNAL BIT TDNN T3,0(P) ;SEE IF THAT IS WHAT CALLER WANTS JRST GTSI20 ;NO. SEARCH USER SIGNALS TDNN T2,CAPENB ;CHECK THAT HE IS ALLOWED SYSTEM SIGNAL RETERR(CAPX1,< SETOM SIGLCK OKSKED>) SKIPA SID,[-NSSIGS,,0] ;SEARCH SYSTEM SIGNALS GTSI20: MOVE SID,[-NUSIGS,,0+NSSIGS] ;SEARCH USER SIGNALS GTSI21: MOVE T2,SIGJOB(SID) AOJE T2,GTSIG3 ;JUMP IF THIS IS A FREE SID AOBJN SID,GTSI21 ;TRY NEXT RETERR(SGNLX2,) ;"NO SIDS AVAILABLE" GTSIG3: MOVSI T2,SIGQUE(SID) MOVEM T2,SIGQUE(SID) ;BE SURE QUEUE IS EMPTY POP P,T2 ;CALLER'S AC1 POP P,SIGJB2(SID) POP P,SIGJB1(SID) HRRE T3,T2 ;GET COUNT MOVNM T3,SIGNAL(SID) ;AND INITIALIZE THE SIGNAL HRR T2,JOBNO ;FORM FLAGS,,JOB MOVEM T2,SIGJOB(SID) ;MAKE THE SIGNAL EXIST SETOM SIGLCK OKSKED HRRZS SID ;SAVE ONLY RIGHT HALF UMOVEM SID,1 ;RETURN SID TO USER JRST SKMRTN ;WITH A SKIP ;RELEASE A SIGNAL ID ;1/ AN SID OR -1 TO RELEASE ALL OWNED BY THIS JOB ; ; RLSIG ; ; ;R+1: ERROR, CODE IN 1 ;R+2: SUCCESS .RLSIG::JSYS MENTR ;ENTER THE MONITOR NOINT ;KEEP ACS STABLE CALL LOCKSG CAMN SID,MINUS1 ;DO ALL SIDS OWNED BY THIS JOB? JRST RLSIG1 ;YES. CAIL SID,0 ;REASONABLE SID? CAIL SID,NSSIGS+NUSIGS RETERR(SGNLX3,) ;"ILLEGAL SID" CALL RLSIG0 ;ACTUALLY RELEASE THE SID RETERR(SGNLX4,) ;"SID NOT OWNED BY THIS JOB" JRST RLSIGX ;INDICATE SUCCESS RLSIG1: MOVNI SID,NSSIGS+NUSIGS HRLZS SID CALL RLSIG0 JFCL ;IGNORE THOSE NOT OWNED BY THIS JOB AOBJN SID,.-2 RLSIGX: SETOM SIGLCK JRST SKMRTN ;RELEASE SID GIVEN BY RH(SID) ;SKIP IF ACTUALLY DONE, NO SKIP IF NOT RLSIG0: HRRZ T2,SIGJOB(SID) ;GET OWNING JOB CAME T2,JOBNO ;THIS JOB? RET ;NO HRRZ T3,SIGQUE(SID) ;CLEAR THE QUEUE RLSG01: JUMPE T3, RLSG02 ;JUMP IF DONE MOVEI T2,0(T3) ;POINTS TO CURRENT ITEM HRRZ T3,0(T2) ;POINTS TO NEXT ITEM SETZM 0(T2) ;CLEAR "DATA PRESENT" AND "SID VALID" JRST RLSG01 ;FOR ALL QUEUED FORKS RLSG02: MOVSI T2,SIGQUE(SID) MOVEM T2,SIGQUE(SID) ;RE INITIALIZE THE QUEUE HEAD SETOM SIGJOB(SID) ;DEASSIGN. CAUSE WTFORS,SIGNLS TO RET! AOS 0(P) RET ;WAIT FOR A SIGNAL EVENT ;1/ FLAGS,,SID ;BIT-1: DON'T WAIT, JUST CHECK ; ;BIT-5: JUST PEEK, DON'T DEQUEUE ; WTFOR ; ;R+1/ ERROR, CODE IN 1 ;R+2/ OK, DATA IN 2, JOB NUMBER OF SIGNL-ING FORK IN RH(3) .WTFOR::JSYS MENTR ;ENTER THE MONITOR PUSH P,1 HRRZ SID,1 ;GET SID CAIL SID,0 ;REASONABLE? CAIL SID,NSSIGS+NUSIGS RETERR(SGNLX3) ;"BAD SID" WTFOR0: NOINT MOVE SID,0(P) ;GET BACK FLAGS CALL LOCKSG ;LOCK THE SIGNAL TABLES MOVE T2,SIGJOB(SID) CAMN T2,MINUS1 ;IN USE? RETERR(SGNLX5,) ;"SID NOT OWNED" HRRZS T2 ;GET JOB NUMBER OF OWNER CAME T2,JOBNO ;THIS JOB? RETERR(SGNLX4,) ;"OWNED BY SOME OTHER JOB" TLNE SID,(1B5) ;"JUST PEEK" JRST WTFOR4 ;YES. NO NEED TO WAIT. TLNE SID,(1B1) ;"DONT WAIT" BIT JRST WTFOR3 ;TRUE. JUST OPERATE ON THE SIGNAL WTFOR1: JSP 4,WTFORT ;WAKE UP ALREADY WAITING? JRST [ SETOM SIGLCK OKINT HRLZ 1,SID ;NO, WAIT FOR IT TO ARRIVE HRRI 1,WTFORT JSYS EDISMS JRST WTFOR0] ;TRY AGAIN WTFOR3: AOSG SIGNAL(SID) ;OPERATE ON THE SIGNAL JRST WTFOR4 ;RESUME SOS SIGNAL(SID) ;UNDO THE AOS TLNE SID,(1B1) ;"DON'T WAIT" RETERR (SGNLX7,) ;"NO SIGNALS WAITING" JRST WTFOR1 ;TRY AGAIN WTFOR4: POP P,SID CALL WT4DAT ;GET THE DATA IF ANY RETERR(SGNLX8,) ;"NO DATA RETURNED" SETOM SIGLCK UMOVEM T2,2 UMOVEM T3,3 ;0,,JOB# JRST SKMRTN ;GET DATA FROM SIGNAL QUEUE ;SKIP IF SUCCESSFUL ;SID/ FLAGS,,SID ;SIGLCK SET AND NOINT ;RETURNS DATA IN T2, AND JOB NUMBER OF FORK WHICH PUT IT THERE IN RH(3) WT4DAT: HRRZ T2,SIGQUE(SID) ;GET OUT POINTER JUMPE T2,WT4DAX ;QUEUE IS EMPTY TLNN SID,(1B5) ;"JUST PEEK", DON'T DEQUEUE CALL DQITEM ;DEQUEUE 1ST ITEM, RETURN DATA IN T2 CALL GTDATA ;COPY DATA OUT OF DEQUEUED ITEM AOS 0(P) ;...AND JOB # OF SIGNL-ER IN RH(3) WT4DAX: RET ;DEQUEUE THE ITEM POINTED TO BY T2 (A FKLIST POINTER) DQITEM: PUSH P,SID LDB SID,[POINT 9,0(T2),17] ;EXTRACT THE SID MOVEI T4,SIGQUE(SID) ;POINTER TO QUEUE HEAD DQITM1: HRRZI T3,0(T4) ;ADVANCE PREDECESSOR POINTER HRRZ T4,0(T3) ;GET CURRENT ITEM CAIE T4,0(T2) ;IS THIS THE ONE TO BE DELETED? JRST DQITM1 ;NO, CDR SOMEMORE DQITM2: HRRZ T4,0(T4) ;SUCCESSOR OF CURRENT ITEM HRRM T4,0(T3) ;BECOMES SUCCESSOR OF PREDECESSOR SKIPN T4 ;AND IF LAST ITEM WAS DEQUEUED HRLM T3,SIGQUE(SID) ;UPDATE THE "IN" POINTER DQITM3: MOVSI T3,(1B0) ANDCAM T3,0(T2) ;CLEAR THE DATA PRESENT FLAG POP P,SID RET ;GET DATA FROM A POSSIBLY DEQUEUED ITEM ;TAKES A FORKX IN T2 ;RETURN DATA IN T2 ;RETURN JOB # OF FORK IN WHICH THE SIGNL WAS DONE IN RH(3) GTDATA: SUBI T2,FKLIST ;GET BACK FORKX HLRZ T3,FKJOB(T2) ;JOB # OF FORK WHICH QUEUED THE DATA MOVE T2,FKDATA(T2) ;FETCH THE DATA WORD FOR CALLER RET USE RESPC ;SCHEDULER TEST FOR ACTIVITY ON A SIGNAL ;AWAKES IF A SIGNAL ARRIVES OR IF THE SID GETS RELEASED WTFORT::SKIPGE SIGNAL(1) ;DID SIGNAL ARRIVE? JRST 1(4) ;YES, WAKE UP MOVE 2,SIGJOB(1) AOJE 2,1(4) ;GOT RELEASED JRST 0(4) USE SWAPPC ;GENERATE A SIGNAL EVENT ;1/ FLAGS,,SID ;B1: DON'T WAIT, B2: DATA SUPPLIED ;2/ DATA ; ; SIGNL ; ;R+1: ERROR, CODE IN 1 ;R+2: OK .SIGNL::JSYS MENTR ;ENTER THE MONITOR NOINT ; Go NOINT here since SGNWAT requires it TLNE 1,(1B2) ;SKIP IF NO DATA SUPPLIED, ELSE ... CALL SGNWAT ;WAIT FOR NOTHING QUEUED BY THIS FORK JFCL UMOVE 1,1 UMOVE 2,2 PUSH P,1 PUSH P,2 HRRZ SID,1 CAIL SID,0 CAIL SID,NSSIGS+NUSIGS RETERR (SGNLX3) CALL LOCKSG MOVE T2,SIGJOB(SID) CAMN T2,MINUS1 RETERR (SGNLX5,) ;"SID NOT OWNED" MOVE T3,JOBNO TLNN T2,(1B3) ;ACCESSIBLE TO ALL JOBS? CAIN T3,0(T2) ;OWNED BY THIS JOB? JRST SIGNL2 ;YES TLNN T2,(1B0) ;ACCESSIBLE TO OTHER JOBS? RETERR (SGNLX4,) ;"SID NOT ACCESSIBLE TO CALLER" SIGNL1: MOVE T2,JOBNO ;SEARCH FOR THIS JOB NUMBER MOVE T3,SIGJB1(SID) ;IN THIS WORD CALL JOBTST SKIPA T2,JOBNO ;NOT THERE, TRY NEXT JRST SIGNL2 ;FOUND, USE IT MOVE T3,SIGJB2(SID) ;TRY THIS WORD NEXT CALL JOBTST RETERR (SGNLX4,) ;"ILLEGAL SID" SIGNL2: POP P,T2 ;DATA POP P,SID TLNE SID,(1B2) ;SKIP IF NO DATA SUPPLIED CALL NQITEM ;QUEUE THE DATA SOS SIGNAL(SID) ;GUNCH THE SIGNAL SETOM SIGLCK TLNE SID,(1B1) ;SKIP IF SUPPOSED TO WAIT JRST SIGNL9 SIGNL4: CALL SGNWAT ;WAIT FOR IT TO BE READ BY WTFOR RETERR(SGNLX5) ;SID GOT RELEASED MOVE T2,FORKX ;INDEX OF THIS FORK LDB T3,[POINT 9,FKLIST(T2),17] ;GET THE SID CAIE T3,0(SID) ;STILL SAME AS WHAT WE STARTED WITH? RETERR (SGNLX6) ;NO. SIGNL WAS DONE AT PSI LEVEL SIGNL9: JRST SKMRTN ;QUEUE SIGNL DATA ;SID/ SID ;T2/ DATA TO BE QUEUED NQITEM: MOVE T3,FORKX ;THIS FORK MOVEM T2,FKDATA(T3) ;STORE THE DATA WORD MOVEI T2,FKLIST(T3) ;POINTER TO CELL IN QUEUE CHAIN MOVSI T3,600000(SID) ;"DATA PRESENT" AND "SID VALID" AND SID MOVEM T3,0(T2) ;STORE IN FKLIST(NEW ITEM) HLRZ T3,SIGQUE(SID) ;GET POINTER TO LAST QUEUED ITEM HRRM T2,0(T3) ;ADD NEW ITEM TO END OF QUEUE HRLM T2,SIGQUE(SID) ;AND UPDATE TAIL POINTER RESKED ;WAKE UP THE SCHEDULER RET ;SKIP IF ITEM QUEDED BY THIS FORK GETS DEQUEUED ;NO SKIP IF SID DISSAPPEARS. CALLED NOINT. RETURNS NOINT. SGNWAT: PUSH P,SID MOVE 1,FORKX ;INDEX OF THIS FORK ADDI 1,FKLIST ;POINTER TO THE FKLIST CELL SGNWA0: SKIPGE T2,0(1) ;ALREADY GONE? JRST [ OKINT CALL DISGE ;NO, HANG UNTIL IT IS NOINT JRST SGNWA0] POP P,SID TLNE T2,(1B1) ;"SID VALID" BIT (CLEARED BY RLSIG) AOS 0(P) RET RESCD ;SIGNAL FACILITY INITIALIZATION ;TO BE CALLED WHEN SYSTEM IS COMING UP SIGINI::MOVNI SID,NSSIGS+NUSIGS HRLZS SID SIGIN1: SETOM SIGJOB(SID) MOVSI T2,SIGQUE(SID) MOVEM T2,SIGQUE(SID) AOBJN SID,SIGIN1 MOVNI T1,NFKS HRLZS T1 SIGIN2: SETZM FKLIST(T1) SETZM FKDATA(T1) AOBJN T1,SIGIN2 SETOM SIGLCK ;UNLOCK THE TABLES RET SWAPCD ;TO BE CALLED BY A FORK KILLING ITSELF (NOINT) SIGKIL::CALL LOCKSG HRRZ T2,FORKX ;SYSTEM INDEX OF THIS FORK SKIPL T3,FKLIST(T2) ;SEE IF ANYTHING QUEUED BY THIS FORK JRST SIGKIX ;NO LDB SID,[POINT 9,T3,17] ;BE VERY SURE OF THAT HRRZ T3,SIGQUE(SID) ;"OUT" POINTER (TO FKLIST) JUMPE T3,SIGKIX ;SHOULD PROBABLY BUGCHK MOVEI T2,0(T3) ;POINTER TO ITEM TO BE REMOVED CALL DQITEM ;DO IT SIGKIX: SETOM SIGLCK RET ;TO BE CALLED BY A JOB GOING AWAY ;REMOVES ALL REFERENCES TO THE JOB FROM SIGJB1,2 RMJBRF::CALL LOCKSG MOVNI SID,NSSIGS+NUSIGS HRLZS SID ;AOBJN POINTER TO SIGNAL TABLES RMJBR0: MOVE T3,SIGJOB(SID) ;FLAGS,,OWNING JOB CAMN T3,MINUS1 ;THIS SIGNAL IN USE? JRST RMJBR4 ;NO, SKIP IT MOVE T2,JOBNO ;OUR JOB NUMBER CAIN T2,0(T3) ;DO WE OWN THIS SID? SETOM SIGJOB(SID) ;YES, RELEASE IT. JUMPGE T3,RMJBR4 ;JUMP IF NO JOBS REFERENCE THIS SID MOVE T3,SIGJB1(SID) ;DATA TO CHECK CALL JOBTST ;IS IT IN THERE? JRST RMJBR2 ;NO, FORGE AHEAD RMJBR1: MOVE T3,SIGJB1(SID) ;GET THE DATA WORD AGAIN CALL REMJBR ;REPLACE ALL JOBNO'S BY 777 MOVEM T3,SIGJB1(SID) ;AND STORE BACK RMJBR2: MOVE T3,SIGJB2(SID) ;SAME FOR OTHER WORD MOVE T2,JOBNO CALL JOBTST JRST RMJBR4 MOVE T3,SIGJB2(SID) CALL REMJBR MOVEM T3,SIGJB2(SID) RMJBR4: AOBJN SID,RMJBR0 ;LOOP OVER ALL SIGS SETOM SIGLCK RET REMJBR: PUSH P,SID ;SAVE SID PUSH P,[POINT 9,T3] PUSH P,[4] MOVEI T2,777 REMJB0: ILDB T1,-1(P) CAMN T1,JOBNO DPB T2,-1(P) SOSLE 0(P) JRST REMJB0 SUB P,[2,,2] POP P,SID RET ;TEST WORD IN T3 FOR NUMBER IN T2 JOBTST: DPB T2,[POINT 9,T2,26] HRLS T2 EQVB T2,T3 JCRY0 .+1 ADD T2,[BYTE (9) 1,1,1,1] EQV T2,T3 JCRY0 .+2 TDNE T2,[BYTE (9) 1,1,1,1] AOS 0(P) RET ;LOCK THE SIGNAL TABLES LOCKSG: PUSH P,SID MOVEI 1,SIGLKT AOSE SIGLCK JSYS EDISMS POP P,SID RET RESCD SIGLKT: AOSE SIGLCK JRST 0(4) JRST 1(4) SWAPCD > ;END IFDEF BEFORE TITLE END